package com.poetize.plus.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.poetize.plus.entity.dto.MenuDTO;
import com.poetize.plus.entity.dto.MenuTreeDTO;
import com.poetize.plus.entity.po.Menu;
import com.poetize.plus.entity.vo.MenuTreeVO;
import com.poetize.plus.entity.vo.MenuVO;
import com.poetize.plus.mapper.MenuMapper;
import com.poetize.plus.service.MenuService;
import com.poetize.plus.utils.BaseConstant;
import com.poetize.plus.utils.RedisUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author zuosy
 * @created 2024/3/29 14:05
 */
@Service
@RequiredArgsConstructor
public class MenuImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService {

    private final RedisUtil redisUtil;

    @Override
    public List<MenuTreeVO> menuTree(MenuTreeDTO menuTreeDTO) {
        List<Menu> menuList = lambdaQuery()
                .eq(Menu::getPartition, menuTreeDTO.partition())
                .like(StringUtils.hasText(menuTreeDTO.name()), Menu::getName, menuTreeDTO.name())
                .list();

        List<MenuTreeVO> menuTreeVOS = BeanUtil.copyToList(menuList, MenuTreeVO.class);
        return menuTreeVOS.stream().filter(menu -> menu.getParentId() == 0)
                .peek(menu -> menu.setChild(getChildren(menu, menuTreeVOS)))
                .sorted(Comparator.comparingInt(MenuTreeVO::getSort)).toList();
    }

    @Override
    public Boolean addMenu(MenuDTO menuDTO) {
        Menu checkMenuName = lambdaQuery()
                .eq(Menu::getPartition, menuDTO.partition())
                .eq(Menu::getName, menuDTO.name())
                .one();
        if (Objects.nonNull(checkMenuName)) {
            throw new IllegalArgumentException("该菜单已存在");
        }
        Menu menu = MenuDTO.convertDTO(menuDTO);
        boolean insert = baseMapper.insert(menu) > 0;
        if (!insert) {
            throw new IllegalArgumentException("数据异常");
        }
        //重新设置home页菜单缓存
        if (menu.getPartition().equals("1")) {
            redisUtil.setHomeRedis(BaseConstant.Redis.HOME_MENU, this::selectHomeMenu);
        }
        return true;
    }

    @Override
    public MenuVO queryMenu(Long id) {
        Menu menu = baseMapper.selectById(id);
        return Optional.ofNullable(menu)
                .map(MenuVO::convert)
                .orElseThrow(() -> new IllegalArgumentException("数据异常"));
    }

    @Override
    public Boolean updateMenu(MenuDTO menuDTO) {
        Menu checkMenuName = lambdaQuery()
                .eq(Menu::getPartition, menuDTO.partition())
                .eq(Menu::getName, menuDTO.name())
                .ne(Menu::getId, menuDTO.id())
                .one();
        if (Objects.nonNull(checkMenuName)) {
            throw new IllegalArgumentException("该菜单已存在");
        }

        Menu menu = MenuDTO.convertDTO(menuDTO);
        boolean update = baseMapper.updateById(menu) > 0;
        if (!update) {
            throw new IllegalArgumentException("数据异常");
        }
        //重新设置home页菜单缓存
        if (menu.getPartition().equals("1")) {
            redisUtil.setHomeRedis(BaseConstant.Redis.HOME_MENU, this::selectHomeMenu);
        }
        return true;
    }

    @Override
    public Boolean deleteMenu(Long id) {
        Menu menu = baseMapper.selectById(id);
        if (Objects.isNull(menu)) {
            throw new IllegalArgumentException("数据异常");
        }
        boolean delete = baseMapper.deleteById(id) > 0;
        if (!delete) {
            throw new IllegalArgumentException("数据异常");
        }
        if (menu.getPartition().equals("1")) {
            redisUtil.setHomeRedis(BaseConstant.Redis.HOME_MENU, this::selectHomeMenu);
        }
        return true;
    }

    @Override
    public List<MenuTreeVO> getHomeMenu() {
        return redisUtil.getHomeRedis(BaseConstant.Redis.HOME_MENU, this::selectHomeMenu);
    }

    /**
     * 菜单树递归
     *
     * @param root
     * @param list
     * @return
     */
    private List<MenuTreeVO> getChildren(MenuTreeVO root, List<MenuTreeVO> list) {
        return list.stream().filter(
                        menu -> Objects.equals(menu.getParentId(), root.getId())
                ).peek(menu ->
                        menu.setChild(getChildren(menu, list))
                )
                .sorted(Comparator.comparingInt(MenuTreeVO::getSort)).toList();
    }

    /**
     * 查询home页菜单数据
     *
     * @return
     */
    private List<MenuTreeVO> selectHomeMenu() {
        MenuTreeDTO menuTreeDTO = new MenuTreeDTO("1", null);
        return menuTree(menuTreeDTO);
    }
}
